import os
import sys
localDir = os.path.dirname(__file__)
curpath = os.path.normpath(os.path.join(os.getcwd(), localDir))
grandparent = os.path.normpath(os.path.join(curpath, '../'))
sys.path.insert(0, grandparent)

import unittest

from sqlalchemy import Table, Column, Integer, String, MetaData, ForeignKey, create_engine

from sqlalchemy.sql import text

from databases.alchemy import Alchemy

config = {"development" : {"db" : "sqlite:///:memory:"}}

class TesterConnection():
    engine = None
    conn = None
    meta = None

    def __init__(self, engine):
        self.meta = MetaData()
        self.engine = engine
        self.conn = self.engine.connect()
        self.meta.bind = self.engine

    def get_version(self):
        s = text("SELECT version FROM schema_info")
        result = ['000']
        result = self.conn.execute(s).fetchone()

        return int(result[0])

    def close(self):
        self.conn.close()

    def create_table(self, name):
        table = Table(name, self.meta,
            Column('version', String(30)),
            useexisting=True,
            )
        self.meta.create_all()
        return table

    def _create_schema(self):
        schema_info = self._schema_table()
        self.meta.create_all()
        self.conn.execute(schema_info.insert(), [{'version' : '000'}])

    def _schema_table(self):
        schema_info = Table('schema_info', self.meta,
            Column('version', String(30)),
            useexisting=True,
            )
        return schema_info

alc, tc = None, None
class TestAlchemy(unittest.TestCase):
    def setUp(self):
        global alc, tc
        alc, tc = build_database()

    def tearDown(self):
        global alc, tc
        alc.close()
        tc.close()

    def testTruth(self):
        self.assertTrue(True)

    def testCreateSchemaInfoIfThereIsNone(self):
        alc = Alchemy(config['development']['db'])
        tc = TesterConnection(alc.engine)
        #Make sure there is not schema_info table
        self.assertRaises(Exception, tc.get_version)

        alc.get_version()
        result = tc.get_version()

        self.assertEquals(0, result)
        alc.close()
        tc.close()

    def testGetVersion(self):
        alc = Alchemy(config['development']['db'])
        tc = TesterConnection(alc.engine)

        tc._create_schema()

        result = alc.get_version()

        self.assertEquals(0, result)
        alc.close()
        tc.close()

    def testUpdateSchemaVersion(self):
        global alc, tc
        alc.get_version()
        alc.update_schema('001')
        result = tc.get_version()

        self.assertEquals(1, result)

    def testRawQuery(self):
        global alc, tc
        alc.get_version()
        alc.execute_raw_query("UPDATE schema_info SET version = '999'")
        result = tc.get_version()

        self.assertEquals(999, result)

    def testDropTable(self):
        global alc, tc
        alc.execute_drop_table(alc.format_table("schema_info"))
        try:
            alc.execute_raw_query("SELECT version FROM schema_info").fetchone()
            self.fail("Should not have found the schema_info table")
        except:
            # Move along people nothing to see here
            pass

def build_database():
    alc = Alchemy(config['development']['db'])
    tc = TesterConnection(alc.engine)
    alc.get_version()
    return alc, tc

if __name__ == "__main__":
    unittest.main()